#include "scene.h"
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

extern char **parse_str(const char *str, char c, unsigned short start, unsigned short end, unsigned short *nsubs);
extern double str2num(const char *str, short nsubs);

static short r_grid_gen(struct grid_config *gc, struct grid *g);
static short th_grid_gen(struct grid_config *gc, struct grid *g);
static short z_grid_gen(struct grid_config *gc, struct grid *g);

extern short grid_gen(struct grid_config *gc, struct grid *g)
 {
  short e;

# ifdef TRACE_FILE
  fprintf(g->trptr, "Entering into 'grid_gen()'...\n");
# endif

  e = r_grid_gen(gc, g);
  if(e >= 0) e = th_grid_gen(gc, g);
  if(e >= 0) e = z_grid_gen(gc, g);

# ifdef TRACE_FILE
  if(e >= 0) fprintf(g->trptr, "...'grid_gen()' ends.\n");
# endif
  return e;
 }


static short r_grid_gen(struct grid_config *gc, struct grid *g)
 {
  FILE *ptr;
  unsigned short i, cnt, n;
  short flag = 1;
  double *r;
  char *str, **s, fname[MAX_FNAME_LEN+1];

# ifdef TRACE_FILE
  fprintf(g->trptr, "Entering into 'r_grid_gen()'...\n");
# endif

  r = g->r;

#ifdef READ_GRID_FILES
  sprintf(fname, "%02d.%s.dat", RUN_CNT-1, R_FILE);
  ptr = (FILE *)fopen(fname, "r");

/* Skip the 1st-line. */
  while(fgetc(ptr) != '\n');

/* Determining maximum line-length. */
  for(n = 0; getc(ptr) != '\n'; n++);

  str = (char *)malloc(sizeof(char)*(n+1));
  rewind(ptr);

/* Skip the 1st-line. */
  while(fgetc(ptr) != '\n');

/* Read the grid-points. */
  for(i = 0; (str[i] = getc(ptr)) != '\n'; i++); str[i] = '\0';
  s = parse_str(str, ' ', 1, 2*NrG+g->nr+1, &n);
  if(n != 2*NrG+g->nr+1)
         {
          fprintf(g->lptr, "ERROR:: In 'r_grid_gen()': the r-grid file '%s' seems to be currupt.\nExiting...\n", fname);
          exit(-1);
         }

  for(i = 0; i < 2*NrG+g->nr+1; i++)
        {
         r[i] = str2num(s[i], 3);
         free(s[i]);
        }

  free(s); free(str); fclose(ptr);

#else

# ifdef r_UNIF_GRID
  for(i = 0; i <= g->nr+NrG; i++) g->r[i+NrG] = g->dr*i;
  cnt = g->nr+2*NrG+1;
# else
  g->r[NrG] = 0;
  cnt = NrG+1;
  for(i = 0; i < gc->nr_center; i++, cnt++) r[cnt] = (i+1)*(dr_CENTER + 0.5*i*gc->r_cd_center);
  for(i = 0; i < gc->nr_mid12; i++, cnt++) r[cnt] = gc->r_mid1 + (i+1)*(gc->dr_mid1 + 0.5*i*gc->r_cd_mid12);
  for(i = 0; i < gc->nr_base; i++, cnt++) r[cnt] = gc->r_mid2 + (i+1)*(dr_MID2 + 0.5*i*gc->r_cd_base);
  for(i = 0; i < g->nr_gap; i++, cnt++) r[cnt] = r_BASE + (i+1)*(gc->dr_base + 0.5*i*gc->r_cd_gap);

/* Ghost cells beyond the cylindrical boundary. */
  for(i = 0; i < NrG; i++, cnt++) r[cnt] = r_CYL + (r_CYL - r[NrG+g->nr-i-1]);
# endif

  for(i = 1; i <= NrG; i++) r[NrG-i] = -r[NrG+i];

#endif

/* Printing the r-gid paramaters in a file. */
  sprintf(fname, "%02d.%s.dat", RUN_CNT, R_FILE);
  ptr = (FILE *)fopen(fname, "w");

/* Printing for backup if needed later in recovering a program. */
  fprintf(ptr, "%d ", g->nr);
  fprintf(ptr, "%d %d %d\n", g->nr_nozzle, g->nr_gap, NrG);

  for(i = 0; i <= 2*NrG+g->nr; i++) fprintf(ptr, "%0.15E ", r[i]);
  fprintf(ptr, "\n----------Don't edit above this line----------\n\n");
  fprintf(ptr, "# nr = %d\n# nr_nozzle = %d\n# nr_gap = %d\n# NrG = %d\n", g->nr, g->nr_nozzle, g->nr_gap, NrG);

  for(i = 0; i <= 2*NrG+g->nr; i++)
           {
            fprintf(ptr, "\n%d\t%E", i-2, r[i]);
            if(i < 2*NrG+g->nr)
               {
                if(i > 0) fprintf(ptr, "\t|------>%E", r[i+1]+r[i-1]-2*r[i]);
                fprintf(ptr, "\n\t\t|------>%E", r[i+1]-r[i]);
                if(r[i+1]-r[i] < 0) flag = -1;
               }
           }
  fprintf(ptr, "\n");

  fclose(ptr);

# ifdef TRACE_FILE
  fprintf(g->trptr, "...'r_grid_gen()' ends.\n");
# endif

  return flag;
 }


static short th_grid_gen(struct grid_config *gc, struct grid *g)
 {
  FILE *ptr;
  unsigned short cnt, i, n;
  short flag = 1;
  char *str, **s, fname[MAX_FNAME_LEN+1];
  double *th;

# ifdef TRACE_FILE
  fprintf(g->trptr, "Entering into 'th_grid_gen()'...\n");
# endif

  th = g->th;

#ifdef READ_GRID_FILES
  sprintf(fname, "%02d.%s.dat", RUN_CNT-1, TH_FILE);
  ptr = (FILE *)fopen(fname, "r");

/* Skip the 1st-line. */
  while(fgetc(ptr) != '\n');

/* Determining maximum line-length. */
  for(n = 0; getc(ptr) != '\n'; n++);

  str = (char *)malloc(sizeof(char)*(n+1));
  rewind(ptr);

/* Skip the 1st-line. */
  while(fgetc(ptr) != '\n');

/* Read the grid-points. */
  for(i = 0; (str[i] = getc(ptr)) != '\n'; i++); str[i] = '\0';
  s = parse_str(str, ' ', 1, 2*NthG+g->nth+1, &n);
  if(n != 2*NthG+g->nth+1)
         {
          fprintf(g->lptr, "ERROR:: In 'th_grid_gen()': the th-grid file '%s' seems to be currupt.\nExiting...\n", fname);
          exit(-1);
         }

  for(i = 0; i < 2*NthG+g->nth+1; i++)
        {
         g->th[i] = str2num(s[i], 3);
         free(s[i]);
        }

  free(s); free(str); fclose(ptr);

#else

# ifdef th_UNIF_GRID
  for(cnt = 0; cnt <= 2*NthG + g->nth; cnt++) g->th[cnt] = (cnt - NthG)*g->dth;
# else
  fprintf(g->lptr, "ERROR:: in 'th_grid_gen()': No definition for non-uniform grid in theta-direction.\n");
  exit(-1);
# endif

#endif

  sprintf(fname, "%02d.%s.dat", RUN_CNT, TH_FILE);
  ptr = (FILE *)fopen(fname, "w");

/* Printing for backup if needed later in recovering a program. */
  fprintf(ptr, "%d %d\n", g->nth, NthG);
  for(i = 0; i <= 2*NthG+g->nth; i++) fprintf(ptr, "%0.15E ", g->th[i]);

  fprintf(ptr, "\n----------Don't edit above this line----------\n");
  fprintf(ptr, "\n# nth = %d\n# NthG = %d\n\n", g->nth, NthG);
  for(i = 0; i <= 2*NthG+g->nth; i++)
           {
            fprintf(ptr, "\n%d\t%E", i-2, th[i]);
            if(i < 2*NthG+g->nth)
               {
                if(i > 0) fprintf(ptr, "\t|------>%E", th[i+1]+th[i-1]-2*th[i]);
                fprintf(ptr, "\n\t\t|------>%E", th[i+1]-th[i]);
                if(th[i+1]-th[i] < 0) flag = -2;
               }
           }
  fprintf(ptr, "\n");

  fclose(ptr);

# ifdef TRACE_FILE
  fprintf(g->trptr, "...'th_grid_gen()' ends.\n");
# endif

  return flag;
 }


static short z_grid_gen(struct grid_config *gc, struct grid *g)
 {
  FILE *ptr;
  short i, flag = 1;
  unsigned short cnt, n;
  double *z;
  char *str, **s, fname[MAX_FNAME_LEN+1];

# ifdef TRACE_FILE
  fprintf(g->trptr, "Entering into 'z_grid_gen()'...\n");
# endif

  z = g->z;

#ifdef READ_GRID_FILES
  sprintf(fname, "%02d.%s.dat", RUN_CNT-1, Z_FILE);
  ptr = (FILE *)fopen(fname, "r");

/* Skip the 1st-line. */
  while(fgetc(ptr) != '\n');

/* Determining maximum line-length. */
  for(n = 0; getc(ptr) != '\n'; n++);

  str = (char *)malloc(sizeof(char)*(n+1));
  rewind(ptr);

/* Skip the 1st-line. */
  while(fgetc(ptr) != '\n');

/* Read the grid-points. */
  for(i = 0; (str[i] = getc(ptr)) != '\n'; i++); str[i] = '\0';
  s = parse_str(str, ' ', 1, 2*NzG+g->nz+1, &n);

  if(n != 2*NzG+g->nz+1)
         {
          fprintf(g->lptr, "ERROR:: In 'z_grid_gen()': the z-grid file '%s' seems to be currupt.\nExiting...\n", fname);
          exit(-1);
         }

  for(i = 0; i < 2*NzG+g->nz+1; i++)
        {
         g->z[i] = str2num(s[i], 3);
         free(s[i]);
        }

  free(s); free(str); fclose(ptr);

#else

# ifdef z_UNIF_GRID
  for(cnt = 0; cnt <= g->nz + 2*NzG; cnt++) z[cnt] = (cnt - NzG)*g->dz;
# else
  z[NzG] = 0;
  cnt = NzG+1;
  for(i = 0; i < nz_UNIF_BOT; i++, cnt++) z[cnt] = z[NzG] + (i+1)*gc->dz_unif_bot;
  for(i = 0; i < gc->nz_mid1; i++, cnt++) z[cnt] = z[NzG+nz_UNIF_BOT] + (i+1)*(gc->dz_unif_bot + 0.5*i*gc->z_cd_bot);
  for(i = 0; i < gc->nz_mid12; i++, cnt++) z[cnt] = gc->z_mid1 + (i+1)*(dz_MID1 + 0.5*i*gc->z_cd_mid12);
  for(i = 0; i < gc->nz_top; i++, cnt++) z[cnt] = gc->z_mid2 + (i+1)*(dz_MID2 + 0.5*i*gc->z_cd_top);

/* Creating ghost-cells at bottom and top. */
  for(i = 0; i < NzG; i++, cnt++) g->z[cnt] = z_TOP + (z_TOP - z[NzG+g->nz-1-i]); /* At the top */
  for(i = 1; i <= NzG; i++) z[NzG-i] = z[NzG]-g->z[NzG+i]; /* At the bottom */

# endif

#endif

/* Printing the z-gid paramaters in a file. */
  sprintf(fname, "%02d.%s.dat", RUN_CNT, Z_FILE);
  ptr = (FILE *)fopen(fname, "w");

/* Printing for backup if needed later in recovering a program. */
  fprintf(ptr, "%d %d\n", g->nz, NzG);

  for(i = 0; i <= 2*NzG+g->nz; i++) fprintf(ptr, "%0.15E ", z[i]);
  fprintf(ptr, "\n");

  fprintf(ptr, "----------Don't edit above this line----------\n");
  fprintf(ptr, "\n# nz = %d\n# NzG = %d\n", g->nz, NzG);

  for(i = 2*NzG+g->nz; i >= 0; i--)
           {
            fprintf(ptr, "\n%d\t%E", i-2, z[i]);
            if(i > 0)
               {
                if(i < 2*NzG+g->nz) fprintf(ptr, "\t|------>%E", z[i+1]+z[i-1]-2*z[i]);
                fprintf(ptr, "\n\t\t|------>%E", z[i]-z[i-1]);
                if(z[i]-z[i-1] < 0) flag = -3;
               }
           }
  fprintf(ptr, "\n");

  fclose(ptr);

# ifdef TRACE_FILE
  fprintf(g->trptr, "...'z_grid_gen()' ends.\n");
# endif

  return 1;
 }
